队列和栈非常类似,但是使用了不同的原则,而非后进先出。
队列是遵循FIFO(First In First Out,先进先出, 也称先来先服务)原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素。最新添加的元素必须排在队列的末尾。
在现实中,最常见的例子就是排队:
排在第一位的人会先接受服务。
创建队列
先从最基本的声明开始:
1 | function Queue(){ |
接下来声明一些队列可用的方法:
enqueue(element(s))
:向队列尾部添加一个(或多个)新的项;dequeue()
:移除队列的第一(即排在队列最前面的)项,并返回被移除的元素;front()
:返回队列中第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动;isEmpty()
:如果队列中不包含任何元素,返回true
,否则返回false
;size()
:返回队列包含的元素个数。
下面是实现的代码:
1 | function Queue() { |
优先队列
队列的一个修改版就是优先队列,即元素的添加和移除是基于优先级的。一个现实的例子就是机场登机的顺序。头等舱和商务舱乘客优先级要高于经济舱乘客。
要实现一个优先队列,有两种选项:设置优先级,然后在正确的位置添加元素;或者用入列操作添加元素,然后按照优先级移除他们。
在这个例子中,我们将会在正确的位置添加元素,因此可以对它们使用默认的出列操作:
1 | function PriorityQueue() { |
它的实现过程是这样的:如果队列为空,可以直接将元素入列。否则,就需要比较该元素与其他元素的优先级。当找到一个比要添加的元素的priority
值更大(优先级更低)的项时,就把新元素插入到它之前。
例如:
1 | var priorityQueue = new PriorityQueue(); |
过程如下:
循环队列——击鼓传花
另一个修改版的队列实现,就是循环队列。循环队列的一个例子就是击鼓传花游戏。
在下面这个示例中,我们要实现一个模拟的击鼓传花游戏:
1 | function hotPotato (nameList, num){ |
在这个函数中,我们输入一份名单,把里面的名字全部加入队列,再给定一个数字,然后迭代队列。
以上算法输出如下:
1 | Camila was eliminated from the Hot Potato game. |
下图模拟了这个输出过程:
可以改变hotPotato
函数的数字,模拟不同的场景。